package com.nickstumpos.android.easyVolume.scheduler.presentation;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

import org.apache.commons.codec.binary.Base64;

import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.RelativeLayout;
import android.widget.Spinner;
import android.widget.TimePicker;
import android.widget.Toast;
import android.widget.ViewSwitcher;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.CompoundButton.OnCheckedChangeListener;

import com.nickstumpos.android.easyVolume.R;
import com.nickstumpos.android.easyVolume.constants.EVCONSTANTS;
import com.nickstumpos.android.easyVolume.preset.types.PresetIdentifier;
import com.nickstumpos.android.easyVolume.scheduler.controller.SchedulePresetController;
import com.nickstumpos.android.easyVolume.scheduler.days.DayOfWeek;
import com.nickstumpos.android.easyVolume.scheduler.dto.SchedulingInfoDto;

public class SchedulePresetActivity extends Activity {

	private ViewSwitcher							group;
	private ListView									scheduleListView;
	private RelativeLayout						scheduleDetailsView;
	private SharedPreferences					settings;
	private SharedPreferences.Editor	editor;
	private Button										saveScheduleButton;
	private CheckBox									recurring;
	private CheckBox									sunday;
	private CheckBox									monday;
	private CheckBox									tuesday;
	private CheckBox									wednesday;
	private CheckBox									thursday;
	private CheckBox									friday;
	private CheckBox									saturday;
	private Spinner										presetSpinner;
	private TimePicker								presetTimePicker;
	private DatePicker								presetDatePicker;
	private List<PresetIdentifier>		presetIdentifiers;
	private EditText									editText;
	private ArrayAdapter<String>			schedulesAdaptor;
	private List<SchedulingInfoDto>		schedules;
	private ArrayAdapter<String>			presets;
	private SchedulePresetController	scheduler;
	private int												currentDisplay;

	private void assignViews() {
		this.group = (ViewSwitcher) this.findViewById(R.id.ViewSwitcher01);
		this.scheduleListView = (ListView) this.findViewById(R.id.schedulesList);
		this.scheduleDetailsView = (RelativeLayout) this
				.findViewById(R.id.scheduleDetails);
		this.recurring = (CheckBox) this.findViewById(R.id.recurring);
		this.saveScheduleButton = (Button) this.findViewById(R.id.saveSchedule);
		this.sunday = (CheckBox) this.findViewById(R.id.sunday);
		this.monday = (CheckBox) this.findViewById(R.id.monday);
		this.tuesday = (CheckBox) this.findViewById(R.id.tuesday);
		this.wednesday = (CheckBox) this.findViewById(R.id.wednesday);
		this.thursday = (CheckBox) this.findViewById(R.id.thursday);
		this.friday = (CheckBox) this.findViewById(R.id.friday);
		this.saturday = (CheckBox) this.findViewById(R.id.saturday);
		this.presetSpinner = (Spinner) this.findViewById(R.id.presetPicker);
		this.presetTimePicker = (TimePicker) this.findViewById(R.id.ScheduledTime);
		this.editText = (EditText) this.findViewById(R.id.ScheduleName);
		this.presetDatePicker = (DatePicker) this.findViewById(R.id.presetDate);
	}

	private void editOrDelete(final int position) {
		AlertDialog ad = new AlertDialog.Builder(this).setTitle("Edit or Delete")
				.setMessage("Do you want to remove or edit this scheduled preset")
				.setPositiveButton("Edit", new DialogInterface.OnClickListener() {

					public void onClick(DialogInterface dialog, int whichButton) {
						SchedulePresetActivity.this
								.setupDetailView(SchedulePresetActivity.this.schedules
										.get(position));
						SchedulePresetActivity.this.schedules.remove(position);
					}
				}).setNegativeButton("Remove", new DialogInterface.OnClickListener() {

					public void onClick(DialogInterface dialog, int whichButton) {
						SchedulePresetActivity.this.scheduler
								.removeScheduledPreset(SchedulePresetActivity.this.schedules
										.get(position).getCode());
						SchedulePresetActivity.this.schedules.remove(position);
						SchedulePresetActivity.this.updateSchedules();
					}
				}).create();
		ad.show();
	}

	private SchedulingInfoDto getDetailState() {
		SchedulingInfoDto sdo = new SchedulingInfoDto();
		if (SchedulePresetActivity.this.sunday.isChecked()) {
			sdo.getDays().add(DayOfWeek.SUNDAY);
		}
		if (SchedulePresetActivity.this.monday.isChecked()) {
			sdo.getDays().add(DayOfWeek.MONDAY);
		}
		if (SchedulePresetActivity.this.tuesday.isChecked()) {
			sdo.getDays().add(DayOfWeek.TUESDAY);
		}
		if (SchedulePresetActivity.this.wednesday.isChecked()) {
			sdo.getDays().add(DayOfWeek.WEDNESDAY);
		}
		if (SchedulePresetActivity.this.thursday.isChecked()) {
			sdo.getDays().add(DayOfWeek.THURSDAY);
		}
		if (SchedulePresetActivity.this.friday.isChecked()) {
			sdo.getDays().add(DayOfWeek.FRIDAY);
		}
		if (SchedulePresetActivity.this.saturday.isChecked()) {
			sdo.getDays().add(DayOfWeek.SATURDAY);
		}
		sdo.setRepeating(SchedulePresetActivity.this.recurring.isChecked());
		Calendar scheduleTime = Calendar.getInstance();
		scheduleTime.set(Calendar.HOUR_OF_DAY,
				SchedulePresetActivity.this.presetTimePicker.getCurrentHour());
		scheduleTime.set(Calendar.MINUTE,
				SchedulePresetActivity.this.presetTimePicker.getCurrentMinute());
		scheduleTime.set(Calendar.YEAR,
				SchedulePresetActivity.this.presetDatePicker.getYear());
		scheduleTime.set(Calendar.MONTH,
				SchedulePresetActivity.this.presetDatePicker.getMonth());
		scheduleTime.set(Calendar.DAY_OF_MONTH,
				SchedulePresetActivity.this.presetDatePicker.getDayOfMonth());
		sdo.setScheduledTime(scheduleTime);
		sdo.setName(SchedulePresetActivity.this.editText.getText().toString());
		long selected = SchedulePresetActivity.this.presetSpinner
				.getSelectedItemId();
		sdo.setPreset(SchedulePresetActivity.this.presetIdentifiers
				.get((int) selected));
		sdo.setSpinnerPosition(this.presetSpinner.getSelectedItemPosition());
		return sdo;
	}

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		this.settings = this.getSharedPreferences(EVCONSTANTS.PREFS_NAME, 0);
		this.editor = this.settings.edit();
		this.scheduler = new SchedulePresetController(this);
		this.setContentView(R.layout.schedulelayout);
		this.setupViews();
		if (savedInstanceState != null) {
			int cur = savedInstanceState.getInt(EVCONSTANTS.SCHED_CURRENT_SCREEN,
					EVCONSTANTS.SCHEDULE_LIST_INDEX);
			if (cur == EVCONSTANTS.SCHEDULE_LIST_INDEX) {
				this.group.setDisplayedChild(EVCONSTANTS.SCHEDULE_LIST_INDEX);
				this.currentDisplay = EVCONSTANTS.SCHEDULE_LIST_INDEX;
			} else {
				this.setupDetailView((SchedulingInfoDto) savedInstanceState
						.getSerializable(EVCONSTANTS.CURRENT_DETAIL_SCREEN));
			}
		} else {
			this.group.setDisplayedChild(EVCONSTANTS.SCHEDULE_LIST_INDEX);
			this.currentDisplay = EVCONSTANTS.SCHEDULE_LIST_INDEX;
		}
	}

	@Override
	public boolean onKeyDown(int keyCode, KeyEvent event) {
		boolean ret = false;
		if (keyCode == KeyEvent.KEYCODE_BACK) {
			if (this.currentDisplay == EVCONSTANTS.SCHEDULE_DETAIL_INDEX) {
				this.returnToListPage();
				ret = true;
			} else {
				this.finish();
				ret = true;
			}
		} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
			ret = true;
		} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
			ret = true;
		} else {
			ret = super.onKeyDown(keyCode, event);
		}
		return ret;
	}

	@Override
	public void onPause() {
		super.onPause();
	}

	@Override
	protected void onSaveInstanceState(Bundle outState) {
		outState.putSerializable(EVCONSTANTS.CURRENT_DETAIL_SCREEN, this.getDetailState());
		outState.putInt(EVCONSTANTS.SCHED_CURRENT_SCREEN, this.currentDisplay);
	}

	@SuppressWarnings("unchecked")
	private void populateListView() {
		this.schedulesAdaptor = new ArrayAdapter<String>(this,
				android.R.layout.simple_list_item_1);
		String listString = this.settings.getString(EVCONSTANTS.LIST_OF_SCHEDULES,
				null);
		if (listString != null) {
			final byte[] buf = Base64.decodeBase64(listString.getBytes());
			ObjectInputStream in = null;
			try {
				in = new ObjectInputStream(new ByteArrayInputStream(buf));
				this.schedules = (List<SchedulingInfoDto>) in.readObject();
				if (this.schedules != null) {
					for (int i = 0; i < this.schedules.size(); i++) {
						this.schedulesAdaptor.add(this.schedules.get(i).getName());
					}
				}
			} catch (final IOException e) {
			} catch (final ClassNotFoundException e) {
			}
		}
		this.schedulesAdaptor.add("+ Add a Scheduled Preset");
		this.scheduleListView.setAdapter(this.schedulesAdaptor);
	}

	private void populateSpinner() {
		this.presetIdentifiers = new ArrayList<PresetIdentifier>();
		this.presets = new ArrayAdapter<String>(this,
				android.R.layout.simple_spinner_item);
		if (this.settings.getString(PresetIdentifier.ONE.getName(), null) != null) {
			this.presets.add(this.settings.getString(EVCONSTANTS.ONE_NAME,
					PresetIdentifier.ONE.getName()));
			this.presetIdentifiers.add(PresetIdentifier.ONE);
		}
		if (this.settings.getString(PresetIdentifier.TWO.getName(), null) != null) {
			this.presets.add(this.settings.getString(EVCONSTANTS.TWO_NAME,
					PresetIdentifier.TWO.getName()));
			this.presetIdentifiers.add(PresetIdentifier.TWO);
		}
		if (this.settings.getString(PresetIdentifier.THREE.getName(), null) != null) {
			this.presets.add(this.settings.getString(EVCONSTANTS.THREE_NAME,
					PresetIdentifier.THREE.getName()));
			this.presetIdentifiers.add(PresetIdentifier.THREE);
		}
		if (this.settings.getString(PresetIdentifier.FOUR.getName(), null) != null) {
			this.presets.add(this.settings.getString(EVCONSTANTS.FOUR_NAME,
					PresetIdentifier.FOUR.getName()));
			this.presetIdentifiers.add(PresetIdentifier.FOUR);
		}
		if (this.settings.getString(PresetIdentifier.FIVE.getName(), null) != null) {
			this.presets.add(this.settings.getString(EVCONSTANTS.FIVE_NAME,
					PresetIdentifier.FIVE.getName()));
			this.presetIdentifiers.add(PresetIdentifier.FIVE);
		}
		if (this.settings.getString(PresetIdentifier.SIX.getName(), null) != null) {
			this.presets.add(this.settings.getString(EVCONSTANTS.SIX_NAME,
					PresetIdentifier.SIX.getName()));
			this.presetIdentifiers.add(PresetIdentifier.SIX);
		}
		if (this.presets.isEmpty()) {
			this.presets.add("No presets set");
			this.presetSpinner.setEnabled(false);
		}
		this.presetSpinner.setAdapter(this.presets);
	}

	private void returnToListPage() {
		this.group.setDisplayedChild(EVCONSTANTS.SCHEDULE_LIST_INDEX);
		this.currentDisplay = EVCONSTANTS.SCHEDULE_LIST_INDEX;
		this.onCreate(null);
	}

	private void setRecurring() {
		this.sunday.setVisibility(View.GONE);
		this.monday.setVisibility(View.GONE);
		this.tuesday.setVisibility(View.GONE);
		this.wednesday.setVisibility(View.GONE);
		this.thursday.setVisibility(View.GONE);
		this.friday.setVisibility(View.GONE);
		this.saturday.setVisibility(View.GONE);
		this.presetDatePicker.setVisibility(View.VISIBLE);
		this.recurring.setOnCheckedChangeListener(new OnCheckedChangeListener() {

			@Override
			public void onCheckedChanged(CompoundButton arg0, boolean checked) {
				if (!checked) {
					SchedulePresetActivity.this.sunday.setVisibility(View.INVISIBLE);
					SchedulePresetActivity.this.monday.setVisibility(View.INVISIBLE);
					SchedulePresetActivity.this.tuesday.setVisibility(View.INVISIBLE);
					SchedulePresetActivity.this.wednesday.setVisibility(View.INVISIBLE);
					SchedulePresetActivity.this.thursday.setVisibility(View.INVISIBLE);
					SchedulePresetActivity.this.friday.setVisibility(View.INVISIBLE);
					SchedulePresetActivity.this.saturday.setVisibility(View.INVISIBLE);
					SchedulePresetActivity.this.presetDatePicker
							.setVisibility(View.VISIBLE);

				} else {
					SchedulePresetActivity.this.sunday.setVisibility(View.VISIBLE);
					SchedulePresetActivity.this.monday.setVisibility(View.VISIBLE);
					SchedulePresetActivity.this.tuesday.setVisibility(View.VISIBLE);
					SchedulePresetActivity.this.wednesday.setVisibility(View.VISIBLE);
					SchedulePresetActivity.this.thursday.setVisibility(View.VISIBLE);
					SchedulePresetActivity.this.friday.setVisibility(View.VISIBLE);
					SchedulePresetActivity.this.saturday.setVisibility(View.VISIBLE);
					SchedulePresetActivity.this.presetDatePicker
							.setVisibility(View.INVISIBLE);
				}
			}

		});
	}

	private void setupDetailView(SchedulingInfoDto dto) {
		if (dto == null) {
			this.editText.setText("Unnamed schedule");
		} else {
			this.sunday.setChecked(dto.getDays().contains(DayOfWeek.SUNDAY));
			this.monday.setChecked(dto.getDays().contains(DayOfWeek.MONDAY));
			this.tuesday.setChecked(dto.getDays().contains(DayOfWeek.TUESDAY));
			this.wednesday.setChecked(dto.getDays().contains(DayOfWeek.WEDNESDAY));
			this.thursday.setChecked(dto.getDays().contains(DayOfWeek.THURSDAY));
			this.friday.setChecked(dto.getDays().contains(DayOfWeek.FRIDAY));
			this.saturday.setChecked(dto.getDays().contains(DayOfWeek.SATURDAY));
			this.recurring.setChecked(dto.isRepeating());
			this.presetDatePicker.updateDate(dto.getScheduledTime()
					.get(Calendar.YEAR), dto.getScheduledTime().get(Calendar.MONTH), dto
					.getScheduledTime().get(Calendar.DAY_OF_MONTH));
			this.presetTimePicker.setCurrentMinute(dto.getScheduledTime().get(Calendar.MINUTE));
			this.presetTimePicker.setCurrentHour(dto.getScheduledTime().get(Calendar.HOUR_OF_DAY));
			this.editText.setText(dto.getName());
			this.presetSpinner.setSelection(dto.getSpinnerPosition());
		}
		this.group.setDisplayedChild(EVCONSTANTS.SCHEDULE_DETAIL_INDEX);
		this.currentDisplay = EVCONSTANTS.SCHEDULE_DETAIL_INDEX;

	}

	private void setupListViewListeners() {
		this.scheduleListView.setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parentView, View childView,
					int position, long id) {
				if (SchedulePresetActivity.this.schedules == null
						|| SchedulePresetActivity.this.schedules.size() <= position) {
					SchedulePresetActivity.this.setupDetailView(null);
				} else {
					SchedulePresetActivity.this.editOrDelete(position);
				}
			}

		});
	}

	private void setupSaveButton() {
		this.saveScheduleButton.setOnClickListener(new OnClickListener() {

			@Override
			public void onClick(View arg0) {
				SchedulingInfoDto sdo = SchedulePresetActivity.this.getDetailState();
				sdo.setCode(SchedulePresetActivity.this.settings.getInt(
						EVCONSTANTS.LAST_CODE_USED, 0) + 1);
				if (SchedulePresetActivity.this.schedules == null) {
					SchedulePresetActivity.this.schedules = new ArrayList<SchedulingInfoDto>();
				}
				long selected = SchedulePresetActivity.this.presetSpinner
						.getSelectedItemId();
				if (selected == AdapterView.INVALID_ROW_ID
						|| SchedulePresetActivity.this.presetIdentifiers
								.get((int) selected) == null) {
					Toast.makeText(SchedulePresetActivity.this,
							"Must select a valid preset", Toast.LENGTH_SHORT).show();
					return;
				}
				sdo.setPreset(SchedulePresetActivity.this.presetIdentifiers
						.get((int) selected));
				SchedulePresetActivity.this.schedules.add(sdo);
				SchedulePresetActivity.this.editor.putInt(EVCONSTANTS.LAST_CODE_USED,
						sdo.getCode());
				SchedulePresetActivity.this.editor.commit();
				SchedulePresetActivity.this.updateSchedules();
				SchedulePresetActivity.this.scheduler.schedulePreset(sdo);
			}
		});
	}

	private void setupViews() {
		this.assignViews();
		this.group.removeAllViews();
		this.group.addView(this.scheduleListView, EVCONSTANTS.SCHEDULE_LIST_INDEX);
		this.group.addView(this.scheduleDetailsView,
				EVCONSTANTS.SCHEDULE_DETAIL_INDEX);
		this.populateSpinner();
		this.populateListView();
		this.setupListViewListeners();
		this.setupSaveButton();
		this.setRecurring();
	}

	private void updateSchedules() {
		try {
			final Base64 encoder = new Base64();
			final ByteArrayOutputStream bos = new ByteArrayOutputStream();
			ObjectOutputStream out = null;
			out = new ObjectOutputStream(bos);
			out.writeObject(this.schedules);
			out.close();
			final byte[] byteParameter = encoder.encode(bos.toByteArray());
			String serialParameter = new String(byteParameter);
			serialParameter = serialParameter.replace("\n", "");
			serialParameter = serialParameter.replace("\r", "");
			SchedulePresetActivity.this.editor.putString(
					EVCONSTANTS.LIST_OF_SCHEDULES, serialParameter);
			SchedulePresetActivity.this.editor.commit();
			SchedulePresetActivity.this.returnToListPage();
		} catch (final IOException e) {
			Toast.makeText(SchedulePresetActivity.this, "Saving Schedule failed",
					Toast.LENGTH_SHORT).show();
		}
	}

}
